Stephan Tolksdorf: fixes the issue in the <atomic> header and adds corresponding tests. I've used macros to fall back to a user-provided default constructor if _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS (though I suspect that there won't be many users defining that macro). The tests use placement new to check that atomic values get properly zero-initialized. I had to modify the atomic_is_lock_free test, because default initialization of an object of const type 'const A' (aka 'const atomic<int>') requires a user-provided default constructor. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@180945 91177308-0d34-0410-b5e6-96231b3b80d8 
diff --git a/CREDITS.TXT b/CREDITS.TXT index 61b3542..34a901f 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT 
@@ -48,6 +48,10 @@  E: kyrtzidis@apple.com  D: Bug fixes.   +N: Bruce Mitchener, Jr. +E: bruce.mitchener@gmail.com +D: Emscripten-related changes. +  N: Michel Morin  E: mimomorin@gmail.com  D: Minor patches to is_convertible. @@ -78,6 +82,10 @@  E: joerg@NetBSD.org  D: NetBSD port.   +N: Stephan Tolksdorf +E: st@quanttec.com +D: Minor <atomic> fix +  N: Michael van der Westhuizen  E: r1mikey at gmail dot com   @@ -93,7 +101,3 @@  E: jyasskin@gmail.com  E: jyasskin@google.com  D: Linux fixes. - -N: Bruce Mitchener, Jr. -E: bruce.mitchener@gmail.com -D: Emscripten-related changes. 
diff --git a/include/__config b/include/__config index 389b6c4..7923f2f 100644 --- a/include/__config +++ b/include/__config 
@@ -216,7 +216,9 @@  # define _LIBCPP_NORETURN __attribute__ ((noreturn))  #endif   +#if !(__has_feature(cxx_defaulted_functions))  #define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#endif // !(__has_feature(cxx_defaulted_functions))    #if !(__has_feature(cxx_deleted_functions))  #define _LIBCPP_HAS_NO_DELETED_FUNCTIONS @@ -422,6 +424,12 @@  #define _LIBCPP_CONSTEXPR constexpr  #endif   +#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#define _LIBCPP_DEFAULT {} +#else +#define _LIBCPP_DEFAULT = default; +#endif +  #ifdef __GNUC__  #define _NOALIAS __attribute__((__malloc__))  #else 
diff --git a/include/atomic b/include/atomic index db67e76..f6ab1cb 100644 --- a/include/atomic +++ b/include/atomic 
@@ -622,7 +622,12 @@  {return __c11_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);}    _LIBCPP_INLINE_VISIBILITY - __atomic_base() _NOEXCEPT {} // = default; +#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS + __atomic_base() _NOEXCEPT = default; +#else + __atomic_base() _NOEXCEPT : __a_() {} +#endif // _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +  _LIBCPP_INLINE_VISIBILITY  _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {}  #ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS @@ -645,7 +650,7 @@  {  typedef __atomic_base<_Tp, false> __base;  _LIBCPP_INLINE_VISIBILITY - __atomic_base() _NOEXCEPT {} // = default; + __atomic_base() _NOEXCEPT _LIBCPP_DEFAULT  _LIBCPP_INLINE_VISIBILITY  _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {}   @@ -726,7 +731,7 @@  {  typedef __atomic_base<_Tp> __base;  _LIBCPP_INLINE_VISIBILITY - atomic() _NOEXCEPT {} // = default; + atomic() _NOEXCEPT _LIBCPP_DEFAULT  _LIBCPP_INLINE_VISIBILITY  _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}   @@ -746,7 +751,7 @@  {  typedef __atomic_base<_Tp*> __base;  _LIBCPP_INLINE_VISIBILITY - atomic() _NOEXCEPT {} // = default; + atomic() _NOEXCEPT _LIBCPP_DEFAULT  _LIBCPP_INLINE_VISIBILITY  _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}   @@ -1367,7 +1372,12 @@  {__c11_atomic_store(&__a_, false, __m);}    _LIBCPP_INLINE_VISIBILITY - atomic_flag() _NOEXCEPT {} // = default; +#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS + atomic_flag() _NOEXCEPT = default; +#else + atomic_flag() _NOEXCEPT : __a_() {} +#endif // _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +  _LIBCPP_INLINE_VISIBILITY  atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {}   
diff --git a/test/atomics/atomics.flag/default.pass.cpp b/test/atomics/atomics.flag/default.pass.cpp index 489e3d2..5c077b0 100644 --- a/test/atomics/atomics.flag/default.pass.cpp +++ b/test/atomics/atomics.flag/default.pass.cpp 
@@ -14,9 +14,18 @@  // atomic_flag() = default;    #include <atomic> +#include <new>  #include <cassert>    int main()  {  std::atomic_flag f; + + { + typedef std::atomic_flag A; + _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {1}; + A& zero = *new (storage) A(); + assert(!zero.test_and_set()); + zero.~A(); + }  } 
diff --git a/test/atomics/atomics.types.generic/address.pass.cpp b/test/atomics/atomics.types.generic/address.pass.cpp index 1cfdef5..af9826f 100644 --- a/test/atomics/atomics.types.generic/address.pass.cpp +++ b/test/atomics/atomics.types.generic/address.pass.cpp 
@@ -66,6 +66,7 @@  // };    #include <atomic> +#include <new>  #include <type_traits>  #include <cassert>   @@ -112,6 +113,13 @@  assert(obj == T(5*sizeof(X)));  assert((obj -= std::ptrdiff_t(3)) == T(2*sizeof(X)));  assert(obj == T(2*sizeof(X))); + + { + _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23}; + A& zero = *new (storage) A();  + assert(zero == 0); + zero.~A(); + }  }    template <class A, class T> 
diff --git a/test/atomics/atomics.types.generic/bool.pass.cpp b/test/atomics/atomics.types.generic/bool.pass.cpp index f6379dc..80e5665 100644 --- a/test/atomics/atomics.types.generic/bool.pass.cpp +++ b/test/atomics/atomics.types.generic/bool.pass.cpp 
@@ -50,6 +50,7 @@  // typedef atomic<bool> atomic_bool;    #include <atomic> +#include <new>  #include <cassert>    int main() @@ -219,4 +220,11 @@  assert((obj = true) == true);  assert(obj == true);  } + { + typedef std::atomic<bool> A; + _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {1}; + A& zero = *new (storage) A();  + assert(zero == false); + zero.~A(); + }  } 
diff --git a/test/atomics/atomics.types.generic/integral.pass.cpp b/test/atomics/atomics.types.generic/integral.pass.cpp index fc678bc..26caa50 100644 --- a/test/atomics/atomics.types.generic/integral.pass.cpp +++ b/test/atomics/atomics.types.generic/integral.pass.cpp 
@@ -85,6 +85,7 @@  // };    #include <atomic> +#include <new>  #include <cassert>    template <class A, class T> @@ -143,6 +144,13 @@  assert(obj == T(7));  assert((obj ^= T(0xF)) == T(8));  assert(obj == T(8)); + + { + _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23}; + A& zero = *new (storage) A();  + assert(zero == 0); + zero.~A(); + }  }    template <class A, class T> 
diff --git a/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp b/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp index 4b09c38..4071989 100644 --- a/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp +++ b/test/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp 
@@ -24,10 +24,10 @@  test()  {  typedef std::atomic<T> A; - const A ct; - bool b1 = std::atomic_is_lock_free(&ct); - const volatile A cvt; - bool b2 = std::atomic_is_lock_free(&cvt); + A t; + bool b1 = std::atomic_is_lock_free(static_cast<const A*>(&t)); + volatile A vt; + bool b2 = std::atomic_is_lock_free(static_cast<const volatile A*>(&vt));  }    struct A